package com.timber.util;

import java.util.*;


public class StringUtils
{
  private static final int[] SEDOL_SEED = { 1, 3, 1, 7, 3, 9 };

  /**
   *  Checks for the occurrence of any character from the checkStr String
   *  in the String str
   *
   *  @param	str		a String to check.
   *  @param	checkStr	a String containing check characters
   *
   */
  public static boolean contains( String str, String checkStr )
  {
    int length = str.length();
    for( int i = 0; i < length; ++i )
    {
      if( checkStr.indexOf( str.charAt( i ) ) >= 0 )
	return true;
    }

    return false;
  }

  /**
   *  Checks for the occurrence of a specified character in the String str
   *
   *  @param	str		a String to check.
   *  @param	checkChar	a character to check for
   *
   */
  public static boolean contains( String str, char checkChar )
  {
    if( str.indexOf( checkChar ) >= 0 )
	return true;
    else
      return false;
  }

  /**
   *  Checks for the occurrence of any numeric character in the
   *  String str
   *
   *  @param	str		a String to check.
   *
   */
  public static boolean hasNumbers( String str )
  {
    boolean ret = contains( str, "0123456789" );
    return ret;
  }

  /**
   *  Checks for the occurrence of any alpha character in the
   *  String str
   *
   *  @param	str		a String to check.
   *
   */
  public static boolean hasLetters( String str )
  {
    boolean ret = contains( str, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
    return ret;
  }

  public static String defaultTickerToUS( String str )
  {
    String ret = "";
    boolean firstTok = true;

    String tok;
    StringTokenizer st = new StringTokenizer( str, "," );
    while( st.hasMoreTokens() )
    {
      if( firstTok )
	firstTok = false;
      else
	ret += ",";

      tok = st.nextToken().trim();
      ret += tok;
      if( tok.indexOf( ' ' ) == -1 && !tok.endsWith( " US" ) )
	ret += " US";
    }

    return ret;
  }

  public static String formatStrToDTC(String s)
  {
    if (s != null) {
       if (s.trim().length() <= 4 && hasNumbers(s) && !hasLetters(s)) {
          s = s.trim();
          int x = s.length();
          for(int i = 0; i + x < 4; i++)  s = "0" + s;
       }
    }
    return s;
  }

  // if string is null, returns empty vector
  public static Vector parseCommaDelimitedString(String s)
  {
    Vector v = new Vector();
    if (s != null)
    {
      String currentString;
      int i = s.indexOf(",");
      while (i > 0)
      {
        currentString = s.substring(0, i);
        s = s.substring(s.indexOf(",")+1) ;
        i = s.indexOf(",");
        v.addElement(currentString);
      }
      v.addElement(s);
    }
    return v;
  }

  /**
   * Counts the elements of @source devided by separotor @delimiter
   *
   * @param	source	    A String of tokens
   * @param	delimiter	A String of one character
   *
   */

   public static int countTokens( String source, String delimiters )
   {
        int count = 0;
        char [] arr = source.toCharArray();

        for(int i = 0; i < arr.length; i++)
        {
            if (delimiters.indexOf( arr[i] ) > -1)
               count++;
        }
        // count of tokens is always one more than the delimiters
        return count+1;
   }


  /**
   * Checks the specified cusip for proper length and correct check digit
   *
   * @param	cusip	A String CUSIP
   *
   */
  public static boolean checkCusip( String cusip )
  {
    if( cusip == null || cusip.length() != 9 )
      return false;

    String myChkDigit = cusip.substring( 8 );
    String subCusip = cusip.substring( 0, 8 );
    String checkDigit = computeCusipCheckDigit( subCusip );
    return checkDigit.equals( myChkDigit );
  }

  /**
   * Computes a CUSIP check digit given an eight character CUSIP
   * (a CUSIP minus the 9th character check digit)
   *
   * @param	subCusip	An eight character CUSIP
   *
   */
  public static String computeCusipCheckDigit( String subCusip )
  {
    int check = 0;
    for( int i = 0; i < subCusip.length(); i++ )
    {
      int ch = subCusip.charAt( i );
      if( ch >= '0' && ch <= '9' )
	ch = ch - '0';
      else
	ch = ch - 'A' + 10;

      int n = ch * ( ( i % 2 ) + 1 );
      for( int mod = n; mod != 0; )
      {
	check = check + mod % 10;
	mod = mod / 10;
      }
    }

    // take last digit and subtract from 10
    check = ( 10 - ( check % 10 ) ) % 10;
    return ( Integer.toString( check ) );
  }

  /**
   * Given an eight character CUSIP returns a nine character CUSIP
   * by adding the ninth character check digit. If given a nine
   * character CUSIP, the given CUSIp is returned unchanged.
   *
   * @param	cusip	An eight or nine character CUSIP
   *
   */
  public static String addCusipCheckDigit( String cusip )
  {
    // if cusip is already 9 digits - nothing to do
    if( cusip.length() == 9 )
      return cusip;
    else
      return cusip + computeCusipCheckDigit( cusip );
  }

  /**
   * Given a six character SEDOL returns a seven character SEDOL
   * by adding the seventh character check digit. If given a seven
   * character SEDOL, the given SEDOL is returned unchanged.
   *
   * @param	sedol	A six or seven character SEDOL
   *
   */
  public static String addSedolCheckDigit( String sedol )
  {
    // if sedol is already 7 digits - nothing to do
    if( sedol.length() >= 7 )
      return sedol;
    else
      return sedol + computeSedolCheckDigit( sedol );
  }

  /**
   * Computes a SEDOL check digit given a six character SEDOL
   * (a SEDOL minus the 7th character check digit)
   *
   * @param	subSedol	A six character SEDOL
   *
   */
  public static String computeSedolCheckDigit( String subSedol )
  {
    // sum of each digit in 6 digit sedol * corresponding value in SEDOL_SEED + check digit
    // must be multiple of 10.
    int check = 0;
    int sum = 0;
    for( int i = 0; i < subSedol.length(); i++ )
    {
      int ch = subSedol.charAt( i );
      ch = ch - '0';
      sum = sum + ( ch * SEDOL_SEED[ i ] );
    }

    // round up to nearest multiple of 10 and subtract sum from it =
    // check digit
    check = ( ( sum + 9 ) / 10 ) * 10 - sum;
    return ( Integer.toString( check ) );
  }

  /**
   * Compare 2 Strings where either or both can be null. 2 null strings are
   * considered equal. null is considered less than non-null. If neither string
   * is null then str1.compareTo(str2) is returned.
   *
   * @param	str1	A string to compare
   * @param	str2	A string to compare
   * @return 	the value <code>0</code> if the argument str1 is equal to
   *		str2; a value less than <code>0</code> if str1
   *		is lexicographically less than the str2 argument; and a
   *		value greater than <code>0</code> if str1 is
   *		lexicographically greater than the str2 argument.
   *
   */
  public static int compareStrings( String str1, String str2 )
  {
    //  If both strings are non-null return result of String.compareTo()
    if( str1 != null && str2 != null )
      return str1.compareTo( str2 );

    //  If both strings are null - consider them "equal"
    if( str1 == null && str2 == null )
      return 0;

    //  One and only one of the strings is null - consider
    //  the non-null one to be greater
    if( str1 == null )
      return -1;
    else
      return 1;
  }
}
